/**
 * 文件名: promise_future_usage_test.cpp
 *
 * 构建:
 *   g++ -std=c++20 -pthread promise_future_usage_test.cpp \
 *       -lgtest -lgtest_main -o promise_future_usage_test
 * 运行:
 *   ./promise_future_usage_test
 *
 * 示例覆盖:
 *   1. 基本值传递 (set_value / get)。
 *   2. 异常传播 (set_exception)。
 *   3. 一次性设置限制 (重复设值触发 future_error)。
 *   4. promise 生命周期提前结束导致 broken_promise。
 *   5. promise 的移动语义。
 *   6. shared_future 多消费者共享结果。
 */

#include <gtest/gtest.h>

#include <chrono>
#include <future>
#include <thread>

using namespace std::chrono_literals;

// -----------------------------------------------------------------------------
// 1) 基础用法：生产者线程设置值，消费者线程等待获取。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, ProducerSetsValueConsumerGets) {
    std::promise<int> promise;

    // get_future() 只能调用一次；返回的 future 与 promise 绑定。
    std::future<int> fut = promise.get_future();

    std::thread producer([&promise] {
        std::this_thread::sleep_for(5ms);  // 模拟耗时
        promise.set_value(42);             // 设置结果后，future 将变为就绪状态
    });

    EXPECT_EQ(fut.get(), 42);              // 阻塞等待并取值
    producer.join();
}

// -----------------------------------------------------------------------------
// 2) 异常传播：promise.set_exception 将异常传递给 future.get()。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, ExceptionPropagatesAcrossThreads) {
    std::promise<int> promise;
    auto fut = promise.get_future();

    std::thread producer([&promise] {
        try {
            throw std::runtime_error("oops");
        } catch (...) {
            // set_exception 需要 std::exception_ptr，可由 std::current_exception() 获取
            promise.set_exception(std::current_exception());
        }
    });

    EXPECT_THROW(fut.get(), std::runtime_error);
    producer.join();
}

// -----------------------------------------------------------------------------
// 3) 一次性约束：重复调用 set_value/set_exception 会抛出 future_error。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, PromiseCanBeSatisfiedOnlyOnce) {
    std::promise<int> promise;
    auto fut = promise.get_future();

    promise.set_value(1);

    // 第二次设值会抛出 promise_already_satisfied
    EXPECT_THROW(
        promise.set_value(2),
        std::future_error
    );

    EXPECT_EQ(fut.get(), 1);
}

// -----------------------------------------------------------------------------
// 4) promise 析构前未设置值，消费者调用 get() 会得到 broken_promise。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, BrokenPromiseWhenValueNotSet) {
    std::future<int> fut;

    {
        std::promise<int> promise;
        fut = promise.get_future();
        // promise 离开作用域被销毁，但未设值/异常
    }

    try {
        fut.get();
        FAIL() << "Expected std::future_error";
    } catch (const std::future_error& err) {
        EXPECT_EQ(err.code(), std::make_error_code(std::future_errc::broken_promise));
    }
}

// -----------------------------------------------------------------------------
// 5) promise 的移动语义：移动后原对象失效，新对象继续持有承诺。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, PromiseSupportsMoveSemantics) {
    std::promise<int> original;
    auto fut = original.get_future();

    std::promise<int> moved = std::move(original);
    // original 已失效，调用其成员将抛出 future_error (no_state)。
    EXPECT_THROW(original.set_value(1), std::future_error);

    std::thread producer([&moved] {
        moved.set_value(123);
    });

    EXPECT_EQ(fut.get(), 123);
    producer.join();
}

// -----------------------------------------------------------------------------
// 6) shared_future：允许多个消费者重复获取同一结果。
// -----------------------------------------------------------------------------
TEST(PromiseFutureUsageTest, SharedFutureAllowsMultipleConsumers) {
    std::promise<std::string> promise;
    auto fut = promise.get_future().share();  // 转换为 shared_future

    std::thread producer([&promise] {
        promise.set_value("hello");
    });

    // 两个消费者线程共享同一个结果
    auto worker = [fut]() mutable {
        return fut.get() + " world";          // shared_future::get() 可多次调用
    };

    auto t1 = std::async(std::launch::async, worker);
    auto t2 = std::async(std::launch::async, worker);

    EXPECT_EQ(t1.get(), "hello world");
    EXPECT_EQ(t2.get(), "hello world");
    producer.join();
}